From dfc0b259c1b59b8b22e4a4b9fa2651deec42bc9d Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 12 Oct 2005 21:10:14 +0100 Subject: [PATCH] Add memory barriers to console ring accesses. Similar to what Rusty uses for xenbus messaging. Signed-off-by: Keir Fraser --- .../drivers/xen/console/xencons_ring.c | 33 +++++--- tools/console/daemon/io.c | 76 ++++++++++--------- 2 files changed, 62 insertions(+), 47 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c index 0b37773575..9dcb60b5c8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c +++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c @@ -34,14 +34,18 @@ int xencons_ring_send(const char *data, unsigned len) { int sent = 0; struct xencons_interface *intf = xencons_interface(); + XENCONS_RING_IDX cons, prod; - while ((sent < len) && - (intf->out_prod - intf->out_cons) < sizeof(intf->out)) { - intf->out[MASK_XENCONS_IDX(intf->out_prod, intf->out)] = - data[sent]; - intf->out_prod++; - sent++; - } + cons = intf->out_cons; + prod = intf->out_prod; + mb(); + BUG_ON((prod - cons) > sizeof(intf->out)); + + while ((sent < len) && ((prod - cons) < sizeof(intf->out))) + intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; + + wmb(); + intf->out_prod = prod; /* Use evtchn: this is called early, before irq is set up. */ notify_remote_via_evtchn(xen_start_info->console_evtchn); @@ -52,16 +56,23 @@ int xencons_ring_send(const char *data, unsigned len) static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs) { struct xencons_interface *intf = xencons_interface(); + XENCONS_RING_IDX cons, prod; - while (intf->in_cons != intf->in_prod) { + cons = intf->in_cons; + prod = intf->in_prod; + mb(); + BUG_ON((prod - cons) > sizeof(intf->in)); + + while (cons != prod) { if (xencons_receiver != NULL) xencons_receiver( - intf->in + MASK_XENCONS_IDX(intf->in_cons, - intf->in), + intf->in + MASK_XENCONS_IDX(cons++, intf->in), 1, regs); - intf->in_cons++; } + wmb(); + intf->in_cons = cons; + return IRQ_HANDLED; } diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c index fc772b7580..9039a96525 100644 --- a/tools/console/daemon/io.c +++ b/tools/console/daemon/io.c @@ -79,44 +79,43 @@ static void evtchn_notify(struct domain *dom) static void buffer_append(struct domain *dom) { struct buffer *buffer = &dom->buffer; - size_t size; - XENCONS_RING_IDX oldcons; - int notify = 0; + XENCONS_RING_IDX cons, prod, size; struct xencons_interface *intf = dom->interface; - while ((size = (intf->out_prod - intf->out_cons)) != 0) { - notify = 1; + cons = intf->out_cons; + prod = intf->out_prod; + mb(); - if ((buffer->capacity - buffer->size) < size) { - buffer->capacity += (size + 1024); - buffer->data = realloc(buffer->data, buffer->capacity); - if (buffer->data == NULL) { - dolog(LOG_ERR, "Memory allocation failed"); - exit(ENOMEM); - } - } - - oldcons = intf->out_cons; - while ((intf->out_cons - oldcons) < size) { - buffer->data[buffer->size] = intf->out[ - MASK_XENCONS_IDX(intf->out_cons, intf->out)]; - buffer->size++; - intf->out_cons++; - } + size = prod - cons; + if ((size == 0) || (size > sizeof(intf->out))) + return; - if (buffer->max_capacity && - buffer->size > buffer->max_capacity) { - memmove(buffer->data + (buffer->size - - buffer->max_capacity), - buffer->data, buffer->max_capacity); - buffer->data = realloc(buffer->data, - buffer->max_capacity); - buffer->capacity = buffer->max_capacity; + if ((buffer->capacity - buffer->size) < size) { + buffer->capacity += (size + 1024); + buffer->data = realloc(buffer->data, buffer->capacity); + if (buffer->data == NULL) { + dolog(LOG_ERR, "Memory allocation failed"); + exit(ENOMEM); } } - if (notify) - evtchn_notify(dom); + while (cons != prod) + buffer->data[buffer->size++] = intf->out[ + MASK_XENCONS_IDX(cons++, intf->out)]; + + mb(); + intf->out_cons = cons; + evtchn_notify(dom); + + if (buffer->max_capacity && + buffer->size > buffer->max_capacity) { + memmove(buffer->data + (buffer->size - + buffer->max_capacity), + buffer->data, buffer->max_capacity); + buffer->data = realloc(buffer->data, + buffer->max_capacity); + buffer->capacity = buffer->max_capacity; + } } static bool buffer_empty(struct buffer *buffer) @@ -419,10 +418,14 @@ static void handle_tty_read(struct domain *dom) char msg[80]; int i; struct xencons_interface *intf = dom->interface; - XENCONS_RING_IDX filled = intf->in_prod - intf->in_cons; + XENCONS_RING_IDX cons, prod; + + cons = intf->in_cons; + prod = intf->in_prod; + mb(); - if (sizeof(intf->in) > filled) - len = sizeof(intf->in) - filled; + if (sizeof(intf->in) > (prod - cons)) + len = sizeof(intf->in) - (prod - cons); if (len > sizeof(msg)) len = sizeof(msg); @@ -441,10 +444,11 @@ static void handle_tty_read(struct domain *dom) } } else if (domain_is_valid(dom->domid)) { for (i = 0; i < len; i++) { - intf->in[MASK_XENCONS_IDX(intf->in_prod, intf->in)] = + intf->in[MASK_XENCONS_IDX(prod++, intf->in)] = msg[i]; - intf->in_prod++; } + wmb(); + intf->in_prod = prod; evtchn_notify(dom); } else { close(dom->tty_fd); -- 2.30.2